﻿using System;
using System.Linq;
using System.Management.Automation;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.ResourceManagement.Client;
using Microsoft.ResourceManagement.ObjectModel;

namespace Quest.FIMPowerShellSnapin
{
    [Cmdlet(VerbsCommon.Get, Constants.Nouns.FIMResource)]
    public class GetFIMResource : PSCmdlet
    {
        private FIMPSSession _session;
        private String _objectID;
        private String _filter;
        private int _resultSetSize;
        private String[] _attributes;
        private String _locale;

        public GetFIMResource()
        {
            _resultSetSize = Constants.DefaultResultSetSize;
        }

        [Parameter(Mandatory = true, ParameterSetName = "ObjectID", Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty]
        public String ObjectID
        {
            get { return _objectID; }
            set { _objectID = value; }
        }

        [Parameter(ParameterSetName = "Filter")]
        [ValidateNotNullOrEmpty]
        public String Filter
        {
            get { return _filter; }
            set { _filter = value; }
        }

        [Parameter(ParameterSetName = "Filter")]
        [ValidateRange(0, int.MaxValue)]
        public int ResultSetSize
        {
            get { return _resultSetSize; }
            set { _resultSetSize = value; }
        }

        [Parameter]
        [ValidateNotNullOrEmpty]
        public String[] Attributes
        {
            get { return _attributes; }
            set { _attributes = value; }
        }

        [Parameter]
        [ValidateNotNullOrEmpty]
        public String Locale
        {
            get { return _locale; }
            set { _locale = value; }
        }

        [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
        [ValidateNotNullOrEmpty]
        public FIMPSSession Session
        {
            get { return _session; }
            set { _session = value; }
        }

        protected override void ProcessRecord()
        {
            if (_attributes == null || _attributes.Count() == 0)
            {
                _attributes = GetDefaultAttributes();
            }
            else
            {
                if (_attributes.Count() == 1 && _attributes[0].ToUpperInvariant() == Constants.AttributeSpecialValueAll)
                {
                    _attributes = null;
                }
                else
                {
                    _attributes = _attributes.Union(GetDefaultAttributes()).ToArray();
                }
            }

            switch (ParameterSetName)
            {
                case "ObjectID":
                    RmReference id = new RmReference(ObjectID); 
                    CultureInfo cultureInfo = (_locale != null) ? new CultureInfo(_locale, false) : null;
                    
                    RmResource specificResource = _session.Client.Get(id, cultureInfo, _attributes);
                    WriteObject(new FIMPSResource(specificResource, _session));
                    break;

                case "Filter":
                    foreach(RmResource resource in _session.Client.Enumerate(_filter, _attributes))
                    {
                        WriteObject(new FIMPSResource(resource, _session));
                    }
                    break;

                default:
                    throw new Exception(Constants.Messages.InternalError_UnknownParameterSet);
            }
        }

        private string[] GetDefaultAttributes()
        {
            List<string> attributeNames = _session.Client.Schema.AllAttributesNames("Resource");
            string[] namesToReturn = new string[attributeNames.Count];

            int i = 0;
            foreach(string attributeName in attributeNames)
            {
                namesToReturn[i++] = attributeName;
            }
            return namesToReturn;
        }
    }
}
